package user

import (
	"context"
	"gitee.com/bobo-rs/creative-framework/pkg/utils"
	"gitee.com/bobo-rs/ecomp-analyzer-services/enums"
	"gitee.com/bobo-rs/ecomp-analyzer-services/framework/dao"
	"gitee.com/bobo-rs/ecomp-analyzer-services/framework/model"
	"gitee.com/bobo-rs/ecomp-analyzer-services/framework/model/entity"
	"gitee.com/bobo-rs/ecomp-analyzer-services/framework/service"
	"gitee.com/bobo-rs/ecomp-analyzer-services/library/exception"
	"gitee.com/bobo-rs/ecomp-analyzer-services/library/models"
	"gitee.com/bobo-rs/ecomp-analyzer-services/library/services/user"
	"github.com/gogf/gf/v2/frame/g"
)

// SendUpdatePwdCaptcha 用户修改密码-发送验证码-第一步
func (u *sUser) SendUpdatePwdCaptcha(ctx context.Context) error {
	uid := service.BizCtx().GetUid(ctx)
	if uid == 0 {
		return exception.NewCode(enums.ErrorNotLogoutIn, ``)
	}

	// 获取用户信息
	var detail entity.User
	err := u.ProcessDetailByUid(ctx, uid, &detail)
	if err != nil {
		return exception.New(err.Error())
	}

	// 验证手机号
	if !utils.IsMobile(detail.Mobile) {
		return exception.New(`手机号未认证，请先认证再修改密码`)
	}

	return service.SmsTpl().SendCaptcha(ctx, detail.Mobile, enums.SmsAliasUptPwdCaptcha)
}

// ValidateUpdatePwdCaptcha 修改密码-校验验证码-第二步
func (u *sUser) ValidateUpdatePwdCaptcha(ctx context.Context, code string) error {
	var (
		detail entity.User
		uid    = service.BizCtx().GetUid(ctx)
	)
	err := u.ProcessDetailByUid(ctx, uid, &detail)
	if err != nil {
		return exception.New(err.Error())
	}

	// 验证短信服务
	if err = service.SmsTpl().ValidateCode(ctx, detail.Mobile, code); err != nil {
		return exception.New(err.Error())
	}

	// 记录缓存校验值
	if err = user.New().SetUpdatePwdCaptcha(ctx, detail.Mobile); err != nil {
		return exception.New(`修改密码-服务异常，请重试`)
	}
	return nil
}

// UpdatePwd 修改密码-修改密码-第三步
func (u *sUser) UpdatePwd(ctx context.Context, in model.UserUpdatePwdInput) error {
	var (
		detail   entity.User
		uid      = service.BizCtx().GetUid(ctx)
		validate = user.New()
	)
	err := u.ProcessDetailByUid(ctx, uid, &detail)
	if err != nil {
		return exception.New(err.Error())
	}

	// 是否已校验过验证码
	if err = validate.UpdatePwdValidate(ctx, detail.Mobile); err != nil {
		return err
	}

	// 销毁校验值
	defer func() {
		if err == nil {
			_ = validate.RemoveUpdatePwdCaptcha(ctx, detail.Mobile)
		}
	}()

	// 生成密码Hash值
	pwdHash, salt, err := utils.GenPasswordHash(in.Pwd)
	if err != nil {
		return exception.New(`生成密码Hash值失败`)
	}

	// 更新密码
	err = u.UpdateUserDetailByUid(ctx, uid, g.Map{
		dao.UserDetail.Columns().PwdHash: pwdHash,
		dao.UserDetail.Columns().PwdSalt: salt,
	})
	if err != nil {
		return exception.New(`修改密码失败，请重试`)
	}

	return nil
}

// SendForgotPwdCaptcha 找回密码-发送短信验证码-第一步
func (u *sUser) SendForgotPwdCaptcha(ctx context.Context, in model.UserForgotPwdSendCaptchaInput) error {
	validate := user.New()

	// 解析加密手机号
	mobile, err := validate.ParseUserForgotPwdParam(ctx, models.UserForgotPwdParseItem{
		AuthSignItem: models.AuthSignItem{
			Sign: in.Sign,
		},
		Mobile: in.Mobile,
	})
	if err != nil {
		return exception.New(err.Error())
	}
	// 设置缓存手机号
	defer func() {
		if err == nil {
			err = validate.SetForgotPwdCache(ctx, mobile, 0)
		}
	}()

	// 验证账户是否存在
	if !u.CheckUserExistsByMobile(ctx, mobile) {
		return exception.New(`账户不存在`)
	}

	// 发送验证码
	return service.SmsTpl().SendCaptcha(ctx, mobile, enums.SmsAliasForgotPwdCaptcha)
}

// ValidateForgotPwdCaptcha 找回密码-检验验证码-第二步
func (u *sUser) ValidateForgotPwdCaptcha(ctx context.Context, in model.UserForgotPwdValidateCaptchaInput) error {
	validate := user.New()
	// 校验规则-检验验证码规则
	r, err := validate.ForgotPwdValidate(ctx, models.ForgotPwdValidateItem{
		Step: 0,
	})
	if err != nil {
		return err
	}

	// 后置缓存校验通过
	defer func() {
		if err == nil {
			err = validate.SetForgotPwdCache(ctx, r.Mobile, 1)
		}
	}()

	// 校验验证码
	return service.SmsTpl().ValidateCode(ctx, r.Mobile, in.Code)
}

// UpdateForgotPwd 找回密码-修改密码-第三步
func (u *sUser) UpdateForgotPwd(ctx context.Context, in model.UserForgotPwdUpdatePwdInput) error {
	var (
		validate = user.New()
		detail   entity.User
	)

	// 校验之前步骤是否发送-用完即销毁
	r, err := validate.ForgotPwdValidate(ctx, models.ForgotPwdValidateItem{
		Step:     1,
		IsRemove: true,
	})
	if err != nil {
		return err
	}

	// 获取用户信息
	err = u.ProcessDetailByMobile(ctx, r.Mobile, &detail)
	if err != nil {
		return exception.NewCode(enums.ErrorForgotNotCaptcha, `找回密码-用户不存在`)
	}

	// 生成密码Hash值
	pwdHash, salt, err := utils.GenPasswordHash(in.Pwd)
	if err != nil {
		return exception.New(err.Error())
	}

	// 修改密码
	return u.UpdateUserDetailByUid(ctx, detail.Id, g.Map{
		dao.UserDetail.Columns().PwdHash: pwdHash,
		dao.UserDetail.Columns().PwdSalt: salt,
	})
}

// UpdateUserDetail 修改用户详情
func (u *sUser) UpdateUserDetail(ctx context.Context, in model.UserUpdateDetailItem) error {
	var (
		uid  = service.BizCtx().GetUid(ctx)
		data = g.Map{
			dao.UserDetail.Columns().Sex:      in.Sex,
			dao.UserDetail.Columns().Birthday: in.Birthday,
			dao.UserDetail.Columns().AttachId: in.AttachId,
		}
		err error
	)

	// 附件ID
	if len(in.AttachId) > 0 {
		data[dao.UserDetail.Columns().Avatar], err = service.Attachment().ProcessAttachUrlByAttachId(ctx, in.AttachId)
		if err != nil {
			return exception.New(`上传头像不存在`)
		}
	}

	// 更新昵称
	if len(in.Nickname) > 0 {
		if err = u.UpdateUserNickname(ctx, uid, in.Nickname); err != nil {
			return err
		}
	}

	// 更新用户详情
	return u.UpdateUserDetailByUid(ctx, uid, data)
}

// UpdateUserDetailByUid 更加用户ID修改用户信息
func (u *sUser) UpdateUserDetailByUid(ctx context.Context, uid uint, data interface{}) error {
	if uid == 0 {
		return exception.New(`缺少用户ID`)
	}
	_, err := dao.UserDetail.Ctx(ctx).
		OmitEmpty().
		Where(dao.UserDetail.Columns().UserId, uid).
		Data(data).
		Update()
	if err != nil {
		return exception.New(`修改用户信息失败`)
	}
	return nil
}

// GetUserAuthDetail 获取授权登录用户详情
func (u *sUser) GetUserAuthDetail(ctx context.Context) *model.UserBasicDetailItem {
	value := service.BizCtx().GetValue(ctx, enums.ContextDataUser)
	if value == nil {
		return nil
	}
	// 断言用户详情
	if detail, ok := value.(*model.UserBasicDetailItem); ok {
		return detail
	}
	return nil
}
